package com.chrray.position.aop;

import com.chrray.position.util.redis.RedisUtils;
import com.chrray.position.util.result.ResponseResults;
import com.chrray.position.util.result.ResultEnum;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.HandlerMapping;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

@Aspect
@Component
public class RepeatSubmitAspect {
    private static final Logger LOGGER = LoggerFactory.getLogger(RepeatSubmitAspect.class);

    @Autowired
    private RedisUtils redisUtils;

    @Pointcut("@annotation(noRepeatSubmit)")
    public void pointCut(NoRepeatSubmit noRepeatSubmit) {
    }

    @Around("pointCut(noRepeatSubmit)")
    public Object around(ProceedingJoinPoint pjp, NoRepeatSubmit noRepeatSubmit) {
        //设置检验时间值 毫秒
        long lockMiSeconds = noRepeatSubmit.lockTime();
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        //将所有参数合并为字符串
        StringBuffer parameterStr = new StringBuffer();
        //获取token
        String token = request.getHeader("accessToken");
        parameterStr.append(" token:" + token);
        // ip地址
        String ipAddr = getRemoteHost(request);
        parameterStr.append(" ip:" + ipAddr);
        // 请求路径
        String requestUrl = request.getRequestURL().toString();
        parameterStr.append(" requestUrl:" + requestUrl);
        //获取@PathVariable修饰的参数
        Map pathVariables = (Map) request.getAttribute(
            HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
        parameterStr.append(" PathVariablesParmeters:" + pathVariables);
        //获取@RequestParam注解参数
        parameterStr.append(" RequestParamParmeters:");
        Map<String, String[]> pramMap = request.getParameterMap();
        for (Map.Entry<String, String[]> entry : pramMap.entrySet()) {
            String mapKey = entry.getKey();
            String mapValue = entry.getValue()[0];
            parameterStr.append(mapKey + ":" + mapValue);
        }
        //获取@RequestBody注解参数
        parameterStr.append(" RequestBodyParmeters:");
        Object[] bodyObjs = pjp.getArgs();
        for (Object bodyParmeter : bodyObjs) {
            parameterStr.append(bodyParmeter);
        }
        Object result = null;
        Object redisObj = redisUtils.get(getKey(token, requestUrl));
        if (redisObj == null) {
            try {
                boolean boo = redisUtils.set(getKey(token, requestUrl), parameterStr, lockMiSeconds);
                if (boo) {
                    result = pjp.proceed();
                    return result;
                } else {
                    result = ResponseResults.fail(ResultEnum.FAIL, "服务器内部错误,请联系管理员");
                    return result;
                }
            } catch (Throwable throwable) {
                result = ResponseResults.fail(ResultEnum.FAIL, "服务器内部错误,请联系管理员");
                return result;
            }
        } else {
            result = ResponseResults.fail(ResultEnum.NO_REPEART, "请勿重复提交");
            return result;
        }
    }

    private String getKey(String token, String path) {
        return token +":"+ path;
    }
    /**
     * 获取目标主机的ip
     *
     * @param request
     * @return
     */
    private String getRemoteHost(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip.contains("0:0:0:0:0:0:0:1") ? "127.0.0.1" : ip;
    }
}


